using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TerritoryGame.Application.Interfaces;
using TerritoryGame.Domain.Entities.App;

namespace TerritoryGame.Application.Services
{
    public class AppGameHistoryService : IAppGameHistoryService
    {
        private readonly List<GameRecord> _gameRecords = new();
        private readonly object _lock = new object();

        public async Task<List<GameRecord>> GetPlayerHistoryAsync(string playerId, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var playerGames = _gameRecords
                    .Where(g => g.PlayerResults.Any(p => p.PlayerId.ToString() == playerId))
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return playerGames;
            }
        }

        public async Task<List<GameRecord>> GetRoomHistoryAsync(string roomId, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var roomGames = _gameRecords
                    .Where(g => g.RoomId.ToString() == roomId)
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return roomGames;
            }
        }

        public async Task<List<GameRecord>> GetGlobalHistoryAsync(int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var globalGames = _gameRecords
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return globalGames;
            }
        }

        public async Task<GameRecord?> GetGameRecordAsync(string gameId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords.FirstOrDefault(g => g.Id.ToString() == gameId);
            }
        }

        public async Task<bool> SaveGameRecordAsync(GameRecord record)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                try
                {
                    // 检查是否已存在
                    var existingRecord = _gameRecords.FirstOrDefault(g => g.Id == record.Id);
                    if (existingRecord != null)
                    {
                        _gameRecords.Remove(existingRecord);
                    }
                    
                    _gameRecords.Add(record);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
        }

        public async Task<bool> DeleteGameRecordAsync(string gameId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                try
                {
                    var record = _gameRecords.FirstOrDefault(g => g.Id.ToString() == gameId);
                    if (record != null)
                    {
                        _gameRecords.Remove(record);
                        return true;
                    }
                    return false;
                }
                catch
                {
                    return false;
                }
            }
        }

        public async Task<List<GameRecord>> GetHistoryByDateRangeAsync(DateTime startDate, DateTime endDate, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var dateRangeGames = _gameRecords
                    .Where(g => g.EndedAt >= startDate && g.EndedAt <= endDate)
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return dateRangeGames;
            }
        }

        public async Task<List<GameRecord>> GetHistoryByPlayerAndDateRangeAsync(string playerId, DateTime startDate, DateTime endDate, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var playerDateRangeGames = _gameRecords
                    .Where(g => g.PlayerResults.Any(p => p.PlayerId.ToString() == playerId))
                    .Where(g => g.EndedAt >= startDate && g.EndedAt <= endDate)
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return playerDateRangeGames;
            }
        }

        public async Task<List<GameRecord>> GetHistoryByRoomAndDateRangeAsync(string roomId, DateTime startDate, DateTime endDate, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var roomDateRangeGames = _gameRecords
                    .Where(g => g.RoomId.ToString() == roomId)
                    .Where(g => g.EndedAt >= startDate && g.EndedAt <= endDate)
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return roomDateRangeGames;
            }
        }

        public async Task<int> GetPlayerGameCountAsync(string playerId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords.Count(g => g.PlayerResults.Any(p => p.PlayerId.ToString() == playerId));
            }
        }

        public async Task<int> GetTotalGameCountAsync()
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords.Count;
            }
        }

        public async Task<int> GetRoomGameCountAsync(string roomId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords.Count(g => g.RoomId.ToString() == roomId);
            }
        }

        public async Task<GameRecord> GetLatestGameByPlayerAsync(string playerId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords
                    .Where(g => g.PlayerResults.Any(p => p.PlayerId.ToString() == playerId))
                    .OrderByDescending(g => g.EndedAt)
                    .FirstOrDefault();
            }
        }

        public async Task<GameRecord> GetLatestGameByRoomAsync(string roomId)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords
                    .Where(g => g.RoomId.ToString() == roomId)
                    .OrderByDescending(g => g.EndedAt)
                    .FirstOrDefault();
            }
        }

        public async Task<List<GameRecord>> GetGamesByStatusAsync(GameStatus status, int page = 1, int pageSize = 20)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                var gamesByStatus = _gameRecords
                    .Where(g => g.Status == status)
                    .OrderByDescending(g => g.EndedAt)
                    .Skip((page - 1) * pageSize)
                    .Take(pageSize)
                    .ToList();

                return gamesByStatus;
            }
        }

        public async Task<Dictionary<string, int>> GetGameCountByStatusAsync()
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords
                    .GroupBy(g => g.Status)
                    .ToDictionary(g => g.Key.ToString(), g => g.Count());
            }
        }

        public async Task<List<GameRecord>> GetTopGamesByDurationAsync(int top = 10)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords
                    .OrderByDescending(g => g.Duration)
                    .Take(top)
                    .ToList();
            }
        }

        public async Task<List<GameRecord>> GetTopGamesByPlayerCountAsync(int top = 10)
        {
            await Task.CompletedTask;
            
            lock (_lock)
            {
                return _gameRecords
                    .OrderByDescending(g => g.PlayerCount)
                    .Take(top)
                    .ToList();
            }
        }
        
        // 记录游戏结果
        public async Task<bool> RecordGameResultAsync(string roomId, object leaderboard)
        {
            await Task.CompletedTask;
            
            try
            {
                // 这里可以根据leaderboard数据创建或更新游戏记录
                // 由于leaderboard是object类型，我们需要进行类型检查和转换
                
                // 创建一个简单的游戏记录（实际实现中可能需要更复杂的逻辑）
                var gameRecord = new GameRecord
                {
                    Id = Guid.NewGuid(),
                    RoomId = Guid.Parse(roomId),
                    Status = GameStatus.Finished,
                    StartedAt = DateTime.UtcNow.AddMinutes(-5), // 假设游戏持续5分钟
                    EndedAt = DateTime.UtcNow,
                    Duration = 300000, // 5分钟，以毫秒为单位
                    PlayerCount = 0, // 需要从leaderboard中获取
                    PlayerResults = new List<PlayerGameResult>() // 需要从leaderboard中构建
                };
                
                // 保存游戏记录
                return await SaveGameRecordAsync(gameRecord);
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}
